﻿#region using
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using XmlGenSharp.Logic.Main.Configuration;
#endregion

namespace XmlGenSharp.Logic.Main
{
  public abstract class GeneratorBase : IGenerator
  {
    // Constructors

    #region GeneratorBase(string inputFileName, string defaultNamespace)
    public GeneratorBase(string inputFileName, string defaultNamespace)
    {
      PreText = string.Empty;
      PostText = string.Empty;

      InputFileName = inputFileName;
      DefaultNamespace = defaultNamespace;
    }
    #endregion

    // Properties

    #region InputFileName
    public string InputFileName
    {
      get;
      set;
    }
    #endregion

    #region DefaultNamespace
    public string DefaultNamespace
    {
      get
      {
        return _defaultNamespace;
      }
      set
      {
        _defaultNamespace = value;
      }
    }
    private string _defaultNamespace = "NotSpecified";
    #endregion

    #region OverwriteIfExists
    public virtual bool OverwriteIfExists
    {
      get
      {
        return false;
      }
    }
    #endregion

    #region PreText
    public string PreText
    {
      get;
      set;
    }
    #endregion

    #region PostText
    public string PostText
    {
      get;
      set;
    }
    #endregion

    // Public Methods

    #region Pluralize(string s)
    public string Pluralize(string s)
    {
      if (s.EndsWith("y"))
        return s.Substring(0, s.Length - 1) + "ies";

      if (s.EndsWith("s"))
        return s + "es";

      return s + "s";
    }
    #endregion

    #region GenerateContent(Config config)
    public virtual byte[] GenerateContent(Config config)
    {
      MemoryStream ms = null;
      StreamWriter writer = null;

      try
      {
        ms = new MemoryStream();
        writer = new StreamWriter(ms);

        GeneratorContext cx = new GeneratorContext(this, config, writer);
        Generate(cx);

        if (writer != null)
        {
          writer.Close();
          writer = null;
        }

        return ms.ToArray();
      }
      catch
      {
        if (writer != null)
        {
          writer.Close();
          writer = null;
        }

        return null;
      }
    }
    #endregion

    #region GetExtension()
    public virtual string GetExtension()
    {
      return ".Generator.cs";
    }
    #endregion

    public abstract string GetFileName();
    public abstract void Generate(IGeneratorContext cx);

    // Protected Methods

    #region ToDotNetTypeName(string typeName)
    protected string ToDotNetTypeName(string typeName)
    {
      switch (typeName.ToLower())
      {
        case "boolean":
          return "bool";

        case "id":
          return "Int64";

        case "idref":
          return "Int64";

        case "string":
          return "string";

        default:
          return typeName;
      }
    }
    #endregion

    #region TypeHelper(string typeName)
    protected TypeHelperBase TypeHelper(string typeName)
    {
      switch (typeName.ToLower())
      {
        case "boolean":
          return BoolTypeHelper.Instance;

        case "id":
          return Int64TypeHelper.Instance;

        case "idref":
          return Int64TypeHelper.Instance;

        case "string":
          return StringTypeHelper.Instance;

        default:
          return ComplexTypeHelper.Instance;
      }
    }
    #endregion

    #region MakePluralPropertyName(string enclosingTypeName, string targetName)
    protected string MakePluralPropertyName(string enclosingTypeName, string targetName)
    {
      return MakePropertyName(enclosingTypeName, Pluralize(targetName));
    }
    #endregion

    #region MakePropertyName(string enclosingTypeName, string targetName)
    protected string MakePropertyName(string enclosingTypeName, string targetName)
    {
      if (enclosingTypeName == targetName)
        return "Inner" + targetName;

      return targetName;
    }
    #endregion

    #region ToCamelCase(string s)
    protected string ToCamelCase(string s)
    {
      return s.Substring(0, 1).ToLower() + s.Substring(1, s.Length - 1);
    }
    #endregion
  }
}

